package com.kxmall.admin.controller.storage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kxmall.admin.controller.storage.service.IKxGoodsOutStorageService;
import com.kxmall.common.core.domain.PageQuery;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.enums.GoodsOutStorageType;
import com.kxmall.common.enums.StorageStatusType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.helper.LoginHelper;
import com.kxmall.storage.domain.KxStorage;
import com.kxmall.storage.domain.KxStorageOutGoods;
import com.kxmall.storage.domain.KxStorageOutProduct;
import com.kxmall.storage.domain.bo.KxStorageOutGoodsBo;
import com.kxmall.storage.domain.bo.KxStorageOutProductBo;
import com.kxmall.storage.domain.vo.KxStorageOutGoodsVo;
import com.kxmall.storage.domain.vo.KxStorageOutProductVo;
import com.kxmall.storage.domain.vo.KxStorageVo;
import com.kxmall.storage.mapper.KxStorageGoodsMapper;
import com.kxmall.storage.mapper.KxStorageMapper;
import com.kxmall.storage.mapper.KxStorageOutGoodsMapper;
import com.kxmall.storage.mapper.KxStorageOutProductMapper;
import com.kxmall.vehicle.domain.KxVehicle;
import com.kxmall.vehicle.mapper.KxVehicleMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 商品出库Service业务层处理
 */
@RequiredArgsConstructor
@Service
public class KxGoodsOutStorageServiceImpl implements IKxGoodsOutStorageService {

    @Autowired
    private KxStorageOutGoodsMapper goodsOutStorageMapper;

    @Autowired
    private KxStorageOutProductMapper outStorageProductMapper;

    @Autowired
    private KxStorageGoodsMapper storageGoodsMapper;

    @Autowired
    private KxStorageMapper storageMapper;

    @Autowired
    private KxVehicleMapper vehicleMapper;
    /**
     * 查询商品出库
     */
    @Override
    public KxStorageOutGoodsVo queryById(Long id) {
        KxStorageOutGoodsVo kxStorageOutGoodsVo = goodsOutStorageMapper.selectVoById(id);
        if(kxStorageOutGoodsVo != null) {
            KxStorage storage = storageMapper.selectById(kxStorageOutGoodsVo.getStorageId());
            if(storage != null){
                kxStorageOutGoodsVo.setStorageName(storage.getName());
            }
            KxVehicle vehicle = vehicleMapper.selectById(kxStorageOutGoodsVo.getVehicleId());
            if(vehicle != null){
                kxStorageOutGoodsVo.setVehicleName(vehicle.getVehicleName());
            }
            List<KxStorageOutProductVo> outStockProductVos = outStorageProductMapper.selectVoList(
                    new LambdaQueryWrapper<KxStorageOutProduct>().eq(KxStorageOutProduct::getOutStockOrder, kxStorageOutGoodsVo.getOutStockOrder()));
            if(outStockProductVos != null) {
                for(KxStorageOutProductVo storageOutProductVo : outStockProductVos){
                    storageOutProductVo.setStorageName(storage.getName());
                }
                kxStorageOutGoodsVo.setOutStorageProductVoList(outStockProductVos);
            }
        }
        return kxStorageOutGoodsVo;
    }

    /**
     * 查询商品出库列表
     */
    @Override
    public TableDataInfo<KxStorageOutGoodsVo> queryPageList(KxStorageOutGoodsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<KxStorageOutGoods> lqw = buildQueryWrapper(bo);
        Page<KxStorageOutGoodsVo> result = goodsOutStorageMapper.selectVoPage(pageQuery.build(), lqw);
        List<KxStorage> storages = storageMapper.selectList();
        List<KxVehicle> vehicles = vehicleMapper.selectList();

        result.getRecords().stream()
                .filter(record -> storages.stream().anyMatch(storage -> storage.getId().equals(record.getStorageId())))
                .forEach(record -> record.setStorageName(storages.stream()
                        .filter(storage -> storage.getId().equals(record.getStorageId()))
                        .findFirst()
                        .map(KxStorage::getName)
                        .orElse(null)));

        result.getRecords().stream()
                .filter(record -> vehicles.stream().anyMatch(vehicle -> vehicle.getId().equals(record.getVehicleId())))
                .forEach(record -> record.setVehicleName(vehicles.stream()
                        .filter(vehicle -> vehicle.getId().equals(record.getVehicleId()))
                        .findFirst()
                        .map(KxVehicle::getVehicleName)
                        .orElse(null)));

        return TableDataInfo.build(result);
    }

    /**
     * 查询商品出库列表
     */
    @Override
    public List<KxStorageOutGoodsVo> queryList(KxStorageOutGoodsBo bo) {
        LambdaQueryWrapper<KxStorageOutGoods> lqw = buildQueryWrapper(bo);
        List<KxStorageOutGoodsVo> result = goodsOutStorageMapper.selectVoList(lqw);
        List<KxStorage> storages = storageMapper.selectList();
        List<KxVehicle> vehicles = vehicleMapper.selectList();
        result.stream()
                .filter(record -> storages.stream().anyMatch(storage -> storage.getId().equals(record.getStorageId())))
                .forEach(record -> record.setStorageName(storages.stream()
                        .filter(storage -> storage.getId().equals(record.getStorageId()))
                        .findFirst()
                        .map(KxStorage::getName)
                        .orElse(null)));

        result.stream()
                .filter(record -> vehicles.stream().anyMatch(vehicle -> vehicle.getId().equals(record.getVehicleId())))
                .forEach(record -> record.setVehicleName(vehicles.stream()
                        .filter(vehicle -> vehicle.getId().equals(record.getVehicleId()))
                        .findFirst()
                        .map(KxVehicle::getVehicleName)
                        .orElse(null)));

        return result;
    }

    private LambdaQueryWrapper<KxStorageOutGoods> buildQueryWrapper(KxStorageOutGoodsBo bo) {
        LambdaQueryWrapper<KxStorageOutGoods> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getVehicleId() != null, KxStorageOutGoods::getVehicleId, bo.getVehicleId());
        lqw.eq(bo.getStorageId() != null, KxStorageOutGoods::getStorageId, bo.getStorageId());
        lqw.eq(StringUtils.isNotBlank(bo.getOutStockOrder()), KxStorageOutGoods::getOutStockOrder, bo.getOutStockOrder());
        lqw.eq(bo.getStates() != null, KxStorageOutGoods::getStates, bo.getStates());
        lqw.eq(StringUtils.isNotBlank(bo.getOutgoingPerson()), KxStorageOutGoods::getOutgoingPerson, bo.getOutgoingPerson());
        lqw.eq(bo.getOutgoingTime() != null, KxStorageOutGoods::getOutgoingTime, bo.getOutgoingTime());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), KxStorageOutGoods::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getOutgoingDay()), KxStorageOutGoods::getOutgoingDay, bo.getOutgoingDay());
        return lqw;
    }

    /**
     * 新增商品出库
     */
    @Override
    public Boolean insertByBo(KxStorageOutGoodsBo bo) {
        //自动生成出库单号,O+年月日+流水号
        //查询数据库最新生成的编号
        KxStorageOutGoods selectByMax = goodsOutStorageMapper.selectByMax();
        String max_code = "";//定义数据库的截取的数据
        String out_skock = "";//定义拼接好的字符串
        if (selectByMax != null) {
            max_code = selectByMax.getOutStockOrder();
        }
        //定义时间字符串拼接
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        String uid_pfix = simpleDateFormat.format(new Date());
        //判断数据库是否有数据
        if (max_code != null && max_code.contains(uid_pfix)) {
            String uid_end = max_code.substring(9, 14);
            Integer endNum = Integer.parseInt(uid_end);
            //100001
            endNum = 100000 + endNum + 1;
            String num = endNum + "";
            //去掉100001中的首位1
            String numm = num.substring(1);
            out_skock = "I" + uid_pfix + numm;
        } else {
            //数据库没数据时
            out_skock = "I" + uid_pfix + "00001";
        }
        //出库商品加出数据库
        List<KxStorageOutProductBo> storageProductBoList = bo.getOutStorageProductBoList();
        if (!CollectionUtils.isEmpty(storageProductBoList)) {
            for (KxStorageOutProductBo storageOutProductBo : storageProductBoList) {
                storageOutProductBo.setOutStockOrder(out_skock);
                KxStorageOutProduct stockProduct = BeanUtil.toBean(storageOutProductBo, KxStorageOutProduct.class);
                if (outStorageProductMapper.insert(stockProduct) <= 0) {
                    throw new ServiceException("出库商品添加失败");
                }
            }
        }
        //出库添加
        KxStorageOutGoods storageOutGoods = BeanUtil.toBean(bo, KxStorageOutGoods.class);
        storageOutGoods.setOutStockOrder(out_skock);
        storageOutGoods.setStates(GoodsOutStorageType.OUT_FOR_STOCK.getCode());
        storageOutGoods.setUpdateTime(new Date());
        if (goodsOutStorageMapper.insert(storageOutGoods) <= 0) {
            throw new ServiceException("管理员系统未知异常");
        }
        return true;

    }

    /**
     * 修改商品出库
     */
    @Override
    public Boolean updateByBo(KxStorageOutGoodsBo bo) {
        LambdaQueryWrapper<KxStorageOutProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(KxStorageOutProduct::getOutStockOrder, bo.getOutStockOrder());
        if (outStorageProductMapper.delete(wrapper) <= 0) {
            throw new ServiceException("出库商品更新失败");
        }
        //出库商品加出数据库
        List<KxStorageOutProductBo> storageProductBoList = bo.getOutStorageProductBoList();
        if (!CollectionUtils.isEmpty(storageProductBoList)) {
            for (KxStorageOutProductBo storageOutProductBo : storageProductBoList) {
                KxStorageOutProduct storageProduct = BeanUtil.toBean(storageOutProductBo, KxStorageOutProduct.class);
                if (outStorageProductMapper.insert(storageProduct) <= 0) {
                    throw new ServiceException("出库商品添加失败");
                }
            }
        }
        KxStorageOutGoods goodsOutStorage = BeanUtil.toBean(bo, KxStorageOutGoods.class);
        goodsOutStorage.setUpdateTime(new Date());
        if (goodsOutStorageMapper.updateById(goodsOutStorage) > 0) {
            return true;
        }
        throw new ServiceException("管理员系统未知异常");

    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(KxStorageOutGoods entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商品出库
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        List<KxStorageOutGoodsVo> goodsOutStorageVoList = goodsOutStorageMapper.selectVoBatchIds(ids);
        //删除出库信息
        if (goodsOutStorageMapper.deleteBatchIds(ids) <= 0) {
            throw new ServiceException("出库商品删除失败");
        }
        for (KxStorageOutGoodsVo goodsOutStorageVo : goodsOutStorageVoList) {
            //批量删除出库商品
            LambdaQueryWrapper<KxStorageOutProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.like(KxStorageOutProduct::getOutStockOrder, goodsOutStorageVo.getOutStockOrder());
            if (outStorageProductMapper.delete(wrapper) <= 0) {
                throw new ServiceException("出库商品删除失败");
            }
        }
        return true;
    }

    @Override
    public Boolean updateOutOfStorage(KxStorageOutGoodsBo bo) {
        if (ObjectUtils.isEmpty(bo.getStorageId()) && StringUtils.isEmpty(bo.getOutStockOrder())) {
            throw new ServiceException("参数不能为空");
        }
        //根据出库的商品数量更新仓库的数量
        LambdaQueryWrapper<KxStorageOutProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KxStorageOutProduct::getOutStockOrder, bo.getOutStorageProductBoList());
        List<KxStorageOutProduct> outStockProducts = outStorageProductMapper.selectList(wrapper);
        Long inStockCount;//出库数量
        for (KxStorageOutProduct outStockProduct : outStockProducts) {
            inStockCount = outStockProduct.getOutStockCount();
            Long productAttrId = outStockProduct.getProductAttrId();
            if (storageGoodsMapper.updateStorageGoods(bo.getStorageId(), productAttrId, inStockCount) <= 0) {
                throw new ServiceException("更新商品库存失败");
            }
        }
        //更新出库状态
        KxStorageOutGoods kxStorageOutGoods = new KxStorageOutGoods();
        kxStorageOutGoods.setStates(GoodsOutStorageType.OUT_FOR_STOCK.getCode());
        kxStorageOutGoods.setOutgoingPerson(LoginHelper.getUsername());
        kxStorageOutGoods.setOutgoingTime(new Date());
        kxStorageOutGoods.setUpdateTime(new Date());
        LambdaQueryWrapper<KxStorageOutGoods> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(KxStorageOutGoods::getOutStockOrder, bo.getOutStockOrder());
        if (goodsOutStorageMapper.update(kxStorageOutGoods, wrapper1) <= 0) {
            throw new ServiceException("商品出库失败");
        }
        return true;
    }

    @Override
    public List<KxStorageVo> storageAllName(KxStorageOutGoodsBo bo) {
        int state = StorageStatusType.NOMRAL.getCode();
        return storageMapper.getStorageNameAll(state, bo.getStorageIds());
    }
}
